/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frhashmap_varfield.c                               */
/*  NOTE      =                                                    */
/*  DATE      = 2014/12/22 by geyh                                 */
/*******************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "frcomm.h"
#include "frlog.h"
#include "frmem.h"
#include "frstr.h"
#include "frlist.h"
#include "frhash2.h"
#include "frhex_dump.h"
#include "frhashmap_varfield.h"

/*******************************************************************************
*  FUNC     :  Frvar_field值节点内容释放
*  ARGS     :  Frvar_field值节点内容
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
static void __frhashmap_varfield_free(Frlist_node *p_st_node)
{
    Frvar_field *p_st_data_field = NULL;
    Frbindata *p_st_value = NULL;

    if(!p_st_node || !p_st_node->data)
        return;

    p_st_data_field = (Frvar_field *)p_st_node->data;

    if(p_st_data_field->p_field_name)
    {
        frfree(p_st_data_field->p_field_name);
        p_st_data_field->p_field_name = NULL;
    }
    switch(p_st_data_field->em_data_type)
    {
        case FRSTRING:
        {
            if (p_st_data_field->field_value.p_value)
            {
                frfree(p_st_data_field->field_value.p_value);
                p_st_data_field->field_value.p_value = NULL;
            }
            break;
        }
        case FRCLOB:
        case FRBLOB:
        {
            p_st_value = (Frbindata *)p_st_data_field->field_value.p_st_value;
            if(p_st_value->p_data)
            {
                frfree(p_st_value->p_data);
                p_st_value->p_data = NULL;
            }
            frfree(p_st_value);
            p_st_data_field->field_value.p_st_value = NULL;
        }
        default:
            break;
    }

    frfree(p_st_data_field);
    p_st_node->data = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  Frvar_field值节点内容出力
*  ARGS     :  Frvar_field值节点
*           :  pp_outbuff出力参数
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
static void __frhashmap_varfield_show(Frlist_node *p_st_node,char **pp_outbuff)
{
    char *p_tmp = NULL;
    char *p_out_hex = NULL;
    Frvar_field *p_st_data_field = NULL;
    Frbindata *p_st_value = NULL;
    unsigned int ui_size = 1024;
    int i_used = 0;

    if(pp_outbuff == NULL || p_st_node == NULL)
        return;

    if(!p_st_node->data)
    {
        *pp_outbuff = NULL;
        return;
    }
    p_tmp = frmalloc(ui_size);
    if(!p_tmp)
        return;

    p_st_data_field = (Frvar_field *)p_st_node->data;
    switch(p_st_data_field->em_data_type)
    {
        case FRINT:
        {
            snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s i_value = %d\n"
                    ,p_st_data_field->p_field_name,"FRINT",p_st_data_field->field_value.i_value);
            break;
        }
        case FRLONG:
        {
            snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s ll_value = %lld\n"
                    ,p_st_data_field->p_field_name,"FRLONG",p_st_data_field->field_value.ll_value);
            break;
        }
        case FRFLOAT:
        {
            snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s f_value = %f\n"
                    ,p_st_data_field->p_field_name,"FRFLOAT",p_st_data_field->field_value.f_value);
            break;
        }
        case FRDOUBLE:
        {
            snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s d_value = %lf\n"
                    ,p_st_data_field->p_field_name,"FRDOUBLE",p_st_data_field->field_value.d_value);
            break;
        }
        case FRSTRING:
        {
            snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s p_value = %s\n"
                    ,p_st_data_field->p_field_name,"FRSTRING",p_st_data_field->field_value.p_value);
            break;
        }
        case FRTIME:
        {
            snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s p_value = %lld\n"
                    ,p_st_data_field->p_field_name,"FRTIME",p_st_data_field->field_value.ll_time_value);
            break;
        }
        case FRCLOB:
        {
            p_st_value = (Frbindata *)p_st_data_field->field_value.p_st_value;
            frhex_dump_to_buffer(p_st_value->p_data,p_st_value->ui_len,&p_out_hex);
            i_used = snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s p_st_value->p_data = %s\n"
                        ,p_st_data_field->p_field_name,"FRCLOB",p_out_hex);
            frfree(p_out_hex);
            break;
        }
        case FRBLOB:
        {
            p_st_value = (Frbindata *)p_st_data_field->field_value.p_st_value;
            frhex_dump_to_buffer(p_st_value->p_data,p_st_value->ui_len,&p_out_hex);
            i_used = snprintf(p_tmp,ui_size,"field_name = %s em_data_type = %s p_st_value->p_data = %s\n"
                        ,p_st_data_field->p_field_name,"FRBLOB",p_out_hex);
            frfree(p_out_hex);
            break;
        }
        default :
        {
            p_tmp[0]='\0';
            break;
        }
    }

    *pp_outbuff = p_tmp;
    return;
}

/*******************************************************************************
*  FUNC     :  生成指定hash表
*  ARGS     :  pp_hash_hdr   (Frhash_header)
*           :  ul_hash_size (hash 数组的大小)
*  RTN      :  成功时返回hash表头, 否则返回NULL
*  NOTE     :  使用frhash_free2释放
*******************************************************************************/
int frhashmap_varfield_create(Frhashmap_header *p_hash_hdr, unsigned long ul_hash_size)
{

    frhash2_create((Frhash_header *)p_hash_hdr,ul_hash_size);
    if(!p_hash_hdr)
        return FR_FAIL;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  生成指定hash表
*  ARGS     :  p_hash_hdr   (*Frhashmap_header)
*           :  ul_hash_size (hash 数组的大小)
*  RTN      :  成功时返回hash表头, 否则返回NULL
*  NOTE     :
*******************************************************************************/
Frhashmap_header *frhashmap_varfield_create2(unsigned long ul_hash_size)
{
    Frhashmap_header *p_hash_hdr=NULL;
    int i_ret_fun;

    p_hash_hdr = frmalloc(sizeof(Frhash_header));
    if(p_hash_hdr==NULL)
        return NULL;

    i_ret_fun = frhashmap_varfield_create(p_hash_hdr, ul_hash_size);
    if(i_ret_fun == FR_FAIL)
    {
        frfree(p_hash_hdr);
    }
    return p_hash_hdr;
}

/*******************************************************************************
*  FUNC     :  释放指定hash表
*  ARGS     :  p_hash_hdr   (*Frhash_header)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frhashmap_varfield_free(Frhashmap_header *p_hash_hdr)
{
    Frlist_header *p_st_list_hdr=NULL;
    unsigned long ul_loop=0L;

    if(p_hash_hdr == NULL || p_hash_hdr->p_list_array == NULL || p_hash_hdr->ul_hash_size <=0)
        return;

    for(ul_loop=0; ul_loop < p_hash_hdr->ul_hash_size; ul_loop++)
    {
        p_st_list_hdr = &(p_hash_hdr->p_list_array[ul_loop]);
        frlist_remove_all(p_st_list_hdr, __frhashmap_varfield_free);
    }

    frfree(p_hash_hdr->p_list_array);
    p_hash_hdr->p_list_array = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  释放指定hash表
*  ARGS     :  p_hash_hdr   (*Frhash_header)
*           :  pf_free      (释放资源用函数指针)
*  RTN      :
*  NOTE     : 使用frhash_create2生成hash头时,需要用该函数释放
*******************************************************************************/
void frhashmap_varfield_free2(Frhashmap_header *p_hash_hdr)
{
    if(p_hash_hdr == NULL)
        return;

    frhashmap_varfield_free(p_hash_hdr);
    frfree(p_hash_hdr);

    return;
}
/*******************************************************************************
*  FUNC     :  Frvar_field值节点内容增加
*  ARGS     :  p_hash_hdr   Frhashmap_header
*           :  p_st_field   要增加的Frvar_field类型的值
*  RTN      :  FR_SUCC      成功
*           :  FR_FAIL      失败
*  NOTE     :
*******************************************************************************/
int frhashmap_varfield_add(Frhashmap_header *p_hash_hdr, Frvar_field *p_st_field)
{
    Frlist_node *p_st_node = NULL;
    char *p_key = NULL;
    unsigned int ui_key_len = 0;
    int i_ret = FR_FAIL;

    if(p_hash_hdr == NULL || p_hash_hdr->p_list_array == NULL || p_st_field == NULL || p_st_field->p_field_name == NULL)
        return i_ret;

    //查询原hashmap中是否存在该key  如果存在则返回FR_FIAL
    p_key = p_st_field->p_field_name;
    ui_key_len = strlen(p_key);
    p_st_node = frhash2_getStr((Frhash_header *)p_hash_hdr, p_key, ui_key_len);
    if(p_st_node)
    {
        __frhashmap_varfield_free(p_st_node);
        p_st_node->data = p_st_field;
        return FR_SUCC;
    }


    //创建节点
    p_st_node = frlist_node_create(p_st_field);
    if(!p_st_node)
        return i_ret;

    i_ret = frhash2_addStr((Frhash_header *)p_hash_hdr, p_key, ui_key_len, p_st_node);
    if(i_ret != FR_SUCC)
    {
        frfree(p_st_node);
        return i_ret;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  hash表里查询指定Frvar_field值节点
*  ARGS     :  p_hash_hdr   (*Frhash_header)
*           :  p_name        (Frvar_field字段名)
*  RTN      :  成功返回Frlist_node *,否则返回NULL
*  NOTE     :
*******************************************************************************/
Frvar_field *frhashmap_varfield_get(Frhashmap_header *p_hash_hdr, char *p_name)
{
    Frlist_node *p_st_node = NULL;
    Frvar_field *p_st_field = NULL;

    if(p_hash_hdr == NULL || p_hash_hdr->p_list_array == NULL || p_name == NULL || *p_name == '\0')
        return NULL;

    p_st_node = frhash2_getStr((Frhash_header *)p_hash_hdr, p_name, strlen(p_name));
    if(p_st_node == NULL)
        return NULL;

    p_st_field = (Frvar_field *)p_st_node->data;

    return p_st_field;
}

/*******************************************************************************
*  FUNC     :  hash表里释放指定Frvar_field值节点
*  ARGS     :  p_hash_hdr   (*Frhash_header)
*           :  p_name        (Frvar_field字段名)
*  RTN      :  FR_SUCC :成功, FR_FAIL :失败
*  NOTE     :
*******************************************************************************/
int frhashmap_varfield_del(Frhashmap_header *p_hash_hdr, char *p_name)
{
    int i_ret = FR_FAIL;

    if(p_hash_hdr == NULL || p_hash_hdr->p_list_array == NULL || p_name == NULL || *p_name == '\0')
        return i_ret;

    i_ret = frhash2_delStr((Frhash_header *)p_hash_hdr, p_name, strlen(p_name), &__frhashmap_varfield_free);

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  节点内容出力
*  ARGS     :  p_hash_hdr       (Frhashmap_header *)
*           :  pp_outbuff       (出力内容指针)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frhashmap_varfield_output(Frhashmap_header *p_hash_hdr, char **pp_outbuff)
{
    Frlist_header *p_st_list_hdr=NULL;
    Frstr *p_st_str=NULL;
    char *p_outbuff_one=NULL;
    unsigned long ul_loop=0L;

    if(p_hash_hdr == NULL || p_hash_hdr->p_list_array == NULL)
       return;

    p_st_str = frstr_new(1024);
    if(p_st_str==NULL)
    {
        frdbg("frstr_new err\n");
        return;
    }

    for(ul_loop=0; ul_loop < p_hash_hdr->ul_hash_size; ul_loop++)
    {
        p_st_list_hdr = &(p_hash_hdr->p_list_array[ul_loop]);
        if( frlist_empty(p_st_list_hdr) == FR_YES )
            continue;

        p_outbuff_one = NULL;
        frlist_show_all(p_st_list_hdr, &p_outbuff_one, __frhashmap_varfield_show);
        if(p_outbuff_one == NULL)
            continue;

        if(p_outbuff_one)

        frstr_append(p_st_str, p_outbuff_one, strlen(p_outbuff_one));
        frfree(p_outbuff_one);
    }
    
    if(pp_outbuff == NULL)
    {
        frdbg("==========================");
        printf("output data\n%s", p_st_str->p_str);
        frdbg("==========================");
        frstr_free(&p_st_str);
    }
    else
    {
        *pp_outbuff = frstr_free2(&p_st_str);
    }
    return;
}
